package bancosys.tec.rtm.monitor;

import java.util.concurrent.TimeUnit;

import bancosys.tec.rtm.exception.ExceptionMonitor;

/**
 * @author Marcio Ribeiro (mmr)
 */
public abstract class AbstractMonitor implements Monitor {
    private boolean shouldStop = false;

    private boolean running = false;

    protected ExceptionMonitor exceptionMonitor;

    /**
     * Inicia thread que chama metodo refresh() de tempos em tempos para atualizar estado do monitor.
     */
    public void startMonitor() {
        if (this.running) {
            throw new MonitorAlreadyRunningException();
        }
        if (this.getRefreshInterval() > 0) {
            new Thread(new Runnable() {
                public void run() {
                    for (;;) {
                        if (AbstractMonitor.this.shouldStop || AbstractMonitor.this.getRefreshInterval() <= 0) {
                            AbstractMonitor.this.running = false;
                            return;
                        }
                        try {
                            AbstractMonitor.this.refresh();
                        } catch (Throwable t) {
                            AbstractMonitor.this.exceptionMonitor.monitor(t);
                        }
                        try {
                            Thread.sleep(TimeUnit.SECONDS.toMillis(AbstractMonitor.this.getRefreshInterval()));
                        } catch (Throwable t) {
                            AbstractMonitor.this.exceptionMonitor.monitor(t);
                        }
                    }
                }
            }).start();
            this.running = true;
        }
    }

    /**
     * @return <code>true</code> se monitor estiver iniciado e em execucao, <code>false</code> se nao.
     */
    public boolean isRunning() {
        return this.running;
    }

    /**
     * Altera variavel de controle que sinaliza que a thread do monitor deve parar.
     */
    public void stopMonitor() {
        this.shouldStop = true;
    }

    /**
     * {@inheritDoc}
     * 
     * @see bancosys.tec.rtm.monitor.Monitor#setExceptionMonitor(bancosys.tec.rtm.exception.ExceptionMonitor)
     */
    public void setExceptionMonitor(ExceptionMonitor exceptionMonitor) {
        this.exceptionMonitor = exceptionMonitor;
    }
}